package com.mucd.chat.service.socketService;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import com.mucd.chat.service.MessageListService;
import com.mucd.chat.service.MessageRecordService;
import com.mucd.chat.service.support.ChatSocketSupport;
import com.mucd.chat.utils.SessionUtil;
import com.mucd.chat.utils.SocketUtils;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.MessageEntity;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.domain.model.OnlineModel;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.websocket.Session;

/**
 * @author mucd
 */
@Service
@Slf4j
public class ChatSocketService {

    @Resource
    private MessageRecordService messageRecordService;
    @Resource
    private MessageListService messageListService;
    @Resource
    private ChatSocketSupport chatSocketSupport;
    @Resource
    private OnlineSocketService onlineSocketService;
    @Resource
    private MessageListSocketService messageListSocketService;

    /**
     * 连接后的操作
     *
     * @param session  session
     * @param myUserId 自己 用户id
     */
    public void socketConnect(Session session, Long myUserId) {
        setOnlineStatus(myUserId, true, session);
    }


    public void socketSendMessage(Session mySession, String message, Long targetUserId, LoginUser myLoginUser) {
        log.info("message:{}", message);

        chatSocketSupport.checkMessage(message);

        OnlineModel targetModel = SessionUtil.get(CacheConstants.CHAT_ONLINE_ON_KEY + targetUserId);
        if (ObjectUtil.isNull(targetModel) || !chatSocketSupport.checkOnline(targetModel.getMySession())) {
            offLineMessage(message, targetUserId, myLoginUser, mySession);
            return;
        }
        //发送给对方
        sendMessage(targetModel.getMySession(), message, myLoginUser.getUserId(), "target");
        //发送给自己
        sendMessage(mySession, message, myLoginUser.getUserId(), "my");

        //保存到消息列表
        messageListService.saveMessageList(myLoginUser.getUserId(), targetUserId, message);

        //保存到消息聊天记录
        messageRecordService.saveMessageRecord(message, targetUserId, myLoginUser.getUserId(), Constants.MESSAGE_ONLINE_TYPE);

        //推送消息列表
        messageListSocketService.sendMessageListCache(message, targetUserId, true);

    }


    /**
     * 根据session发送消息
     *
     * @param session  指定好友的session 也可以是自己的
     * @param message  消息内容
     * @param userId   好友id 也可以是自己的
     * @param sendSign 发送标识,target:对方,my:自己
     */
    private void sendMessage(Session session, String message, Long userId, String sendSign) {
        SocketUtils util = SpringUtils.getBean(SocketUtils.class);
        LoginUser loginUser = util.getLoginUser(userId);

        MessageEntity entity = new MessageEntity();
        entity.setMessage(message);
        entity.setAvatar(loginUser.getUser().getAvatar());
        entity.setSendSign(sendSign);

        session.getAsyncRemote().sendText(JSONObject.toJSONString(R.ok(entity)));
    }


    /*public void socketSendMessage(Session mySession, String message, Long targetUserId, LoginUser myLoginUser) {
        log.info("message:{}", message);

        chatSocketSupport.checkMessage(message);

        OnlineModel targetModel = SessionUtil.get(CacheConstants.CHAT_ONLINE_ON_KEY + targetUserId);
        //如果为空可能是不在线,保存为离线消息
        if (ObjectUtil.isNull(targetModel)) {
            //处理离线消息
            offLineMessage(message, targetUserId, myLoginUser);
            return;
        }

        Session targetSession = targetModel.getMySession();

        //是否在线,不在线保存为离线消息
        boolean b = chatSocketSupport.checkOnline(targetSession);
        if (!b) {
            //处理离线消息
            offLineMessage(message, targetUserId, myLoginUser);
            return;
        }

        SocketUtils util = SpringUtils.getBean(SocketUtils.class);
        LoginUser targetLoginUser = util.getLoginUser(targetUserId);

        MessageEntity target = new MessageEntity();
        target.setMessage(message);
        target.setAvatar(targetLoginUser.getUser().getAvatar());
        target.setSendSign("target");

        targetSession.getAsyncRemote().sendText(JSONObject.toJSONString(R.ok(target)));

        MessageEntity my = new MessageEntity();
        my.setMessage(message);
        my.setAvatar(myLoginUser.getUser().getAvatar());
        my.setSendSign("my");

        mySession.getAsyncRemote().sendText(JSONObject.toJSONString(R.ok(my)));
        //保存聊天记录
    }*/

    /**
     * 离线消息
     * 还需要判断是否登录,如果登录就算在线
     * @param message      消息内容
     * @param friendUserId 好友用户id
     * @param myLoginUser  自己的登录信息
     * @param mySession    自己的session
     */
    public void offLineMessage(String message, Long friendUserId, LoginUser myLoginUser, Session mySession) {

        //判断是否登录,如果登陆了就是在线消息, 在线返回true 和好友 Session
        Pair<Boolean, Session> selectedOnlineStatus = onlineSocketService.selectOnlineStatus(friendUserId);

        //在线
        if (selectedOnlineStatus.getKey()) {
            Session session = selectedOnlineStatus.getValue();
            //发送给对方
            sendMessage(session, message, friendUserId, "target");
            //发送给自己
            sendMessage(mySession, message, myLoginUser.getUserId(), "my");

            //消息列表
            messageListService.saveMessageList(myLoginUser.getUserId(), friendUserId, message);
            //消息聊天记录
            messageRecordService.saveMessageRecord(message, friendUserId, myLoginUser.getUserId(), Constants.MESSAGE_ONLINE_TYPE);
            //推送消息列表
            messageListSocketService.sendMessageListCache(message, friendUserId, true);

        } else {
            //不在线

            //发送给自己
            sendMessage(mySession, message, myLoginUser.getUserId(), "my");

            //消息列表
            messageListService.saveMessageList(myLoginUser.getUserId(), friendUserId, message);
            //消息聊天记录
            messageRecordService.saveMessageRecord(message, friendUserId, myLoginUser.getUserId(), Constants.MESSAGE_OFFLINE_TYPE);

            //推送消息列表
            messageListSocketService.sendMessageListCache(message, friendUserId, false);

        }


    }


    public void socketDisconnect(Session session) {

    }

    /**
     * 设置在线离线状态
     *
     * @param myUserId 自己用户id
     * @param online   true:在线 false:离线
     */
//    @SneakyThrows
    public void setOnlineStatus(Long myUserId, boolean online, Session session) {
        OnlineModel model = new OnlineModel();
        model.setMyUserId(myUserId);
        model.setMySession(session);

        if (online) {
            model.setOnLineDate(DateUtil.date());
            model.setOnline(true);

            SessionUtil.put(CacheConstants.CHAT_ONLINE_ON_KEY + myUserId, model);
//            redisCache.setCacheObject(session.getId(), true);


        }
//        redisCache.setCacheObject(CacheConstants.CHAT_ONLINE_ON_KEY + myUserId, model);
    }

    private void setOfflineStatus(Long myUserId, boolean online, Session session) {
        OnlineModel model = new OnlineModel();
        model.setMyUserId(myUserId);
        model.setOnline(false);
        model.setOffLineDate(DateUtil.date());

        SessionUtil.put(CacheConstants.CHAT_ONLINE_OFF_KEY + myUserId, model);
//        redisCache.setCacheObject(CacheConstants.CHAT_ONLINE_OFF_KEY + myUserId, model);
    }

}
